﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CrossLayerCommunication
{    
    public class OperationResult<U> : OperationResult, IOperationResult<U>
    {        
        public U Data
        {
            get;
            protected set;
        }

        protected OperationResult()
            :base()
        {            
        }

        public OperationResult(IEnumerable<IMessage> errors)
            : base(errors.ToArray())
        {
        }

        public OperationResult(params IMessage[] errors)
            : base(errors)
        {            
        }

        public OperationResult(U extraParameter = default(U))
            : this()
        {
            Data = extraParameter;
        }
    }

    public class OperationResult : IOperationResult
    {
        public static OperationResult OK
        {
            get { return new OperationResult(); }
        }       

        public bool WasSuccessful
        {
            get { return Messages.Where(item=>item.Type == MessageType.Error).Count() == 0; }
        }

        protected Dictionary<int, IMessage> _Messages;
        public IEnumerable<IMessage> Messages
        {
            get { return _Messages.Values; }
        }

        public OperationResult()
        {
            _Messages = new Dictionary<int, IMessage>();
        }

        public OperationResult(params IMessage[] messages)
            : this()
        {
            if (messages != null &&
                messages.Length > 0)
                this._Messages = messages.Where(item => item != null).ToDictionary(key=>key.Id, value=>value);
        }

        public void AddMessages(params IMessage[] messages)
        {
            if (messages == null || messages.Length == 0)
                return;

            foreach (IMessage message in messages)
            {
                IMessage containedMessage;
                if (this._Messages.TryGetValue(message.Id, out containedMessage))
                {
                    if (containedMessage.Params == null ||
                        containedMessage.Params.Length == 0)
                    {
                        containedMessage.Params = message.Params;
                        containedMessage.Key = message.Key;
                    }
                }
                else 
                {
                    this._Messages.Add(message.Id, (IMessage)message.Clone());
                }
            }
        }
    }
}
